/**
 * parser transfer的数据格式,也是返回的数据结构
 * parserTreeNode 树形结构节点数据格式
 * 不用condition原因是以为dom节点还会存在树上
 */
import React, { Component, PropTypes } from "react"
import { connect } from 'react-redux'
import Transfer from "components/transfer"
import { Tree, message, Spin, Checkbox } from 'antd'
import httpFetch from "share/httpFetch"
import { messages } from "share/common"
import "styles/components/template/department.scss"
import debounce from 'lodash.debounce'

const { TreeNode } = Tree;

@connect(mapStateToProps)
class DepartmentTransfer extends Component {

  constructor(props) {
    super(props);
    const { value } = props;
    let temp = (value || []).map(item => Object.assign(item, {
      id: item.id || item.departmentOID,
      title: item.title || item.name || item.path
    }));
    this.state = {
      targetKeys: temp.map(item => item.id),
      toData: [],
      loading: false,
      dataSource: temp,
      isRelated: false,
      searchValue: ''
    };
    this.search = debounce(this.search, 250);
  }

  componentDidMount () {
    const { onRef } = this.props;
    onRef && (onRef(this));
    this.getList();
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.companyId !== this.props.companyId) {
      this.setState({ searchValue: '' }, this.getList);
    }
  }

  parser = item => {
    const { parser } = this.props;
    let temp = parser(item);
    !temp.hasOwnProperty('id') && (temp.id = item.departmentOID);
    !temp.hasOwnProperty('title') && (temp.title = temp.hasOwnProperty('name') ? item.name : item.path);
    return temp;
  };

  parserTreeNode = item => {
    let temp = this.parser(item);
    return {
      title: temp.title,
      key: temp.id,
      isLeaf: !item.hasChildrenDepartments,
      departmentOID: item.departmentOID,
      id: item.id
    }
  };

  getUrl = (type, params) => {
    const { company, isNeedCompany, companyId } = this.props;
    let url;
    switch (type) {
      case 'init':
        url = `/api/departments/root/v2?flag=1002`;
        break;
      case 'onload':
        url = `/api/department/child/${params}?flag=1002`;
        break;
      case 'checked':
        url = `/api/department/cascade?departmentId=${params}&status=101&includeChild=true`;
        break;
      case 'search':
        url = `/api/department/tenant/keyword/v2?status=101&keyword=${encodeURIComponent(params)}`;
        break;
      default:
        break;
    }
    if (isNeedCompany) {
      url += `&companyId=${company.id}`;
    }
    if (companyId) {
      url += `&companyId=${companyId}`;
    }
    return url
  };

  getList = () => {
    this.setState({ loading: true });
    httpFetch.get(this.getUrl('init')).then(res => {
      this.setState({
        toData: res.data.map(item => this.parserTreeNode(item)),
        loading: false,
        dataSource: this.getDataSource(res.data.map(item => this.parser(item)))
      });
    }).catch(() => {
      message.error(messages('common-1.key289')/*系统异常*/);
      this.setState({ loading: false });
    })
  };

  getDataSource = data => {
    const { dataSource } = this.state;
    let temp = [...data, ...dataSource];
    const res = new Map();
    return temp.filter(item => !res.has(item.id) && res.set(item.id, 1));
  };

  onLoadData = treeNode => {
    return new Promise((resolve) => {
      if (treeNode.props.children) {
        resolve(treeNode.props.children);
        return;
      }
      httpFetch.get(this.getUrl('onload', treeNode.props.dataRef.departmentOID)).then(res => {
        treeNode.props.dataRef.children = res.data.map(item => this.parserTreeNode(item));
        this.setState({ dataSource: this.getDataSource(res.data.map(item => this.parser(item))) });
        resolve(res);
      })
    });
  };

  renderTreeNodes = data => {
    const { targetKeys } = this.state;
    return data.map((item) => {
      let disabled = (this.props.needEntity && !item.isEntity) || targetKeys.includes(item.key);
      if (item.children) {
        return (
          <TreeNode title={item.title} key={item.key} dataRef={item} disabled={disabled}>
            {this.renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return <TreeNode {...item} dataRef={item} disabled={disabled}/>;
    });
  };

  onCheck = (values, e, onItemSelect) => {
    const { isRelated } = this.state;
    if (isRelated && !e.node.props.isLeaf) {
      this.setState({ loading: true });
      httpFetch.get(this.getUrl('checked', e.node.props.dataRef.id)).then(res => {
        let departmentList = this.getDepartmentList(res.data);
        departmentList.map(item => {
          onItemSelect(item.id, e.checked);
        });
        this.setState({ loading: false, dataSource: this.getDataSource(departmentList) });
      }).catch(e => {
        this.setState({ loading: false });
        message.error(e.response.data.message);
      })
    } else {
      onItemSelect(e.node.props.eventKey, e.checked)
    }
  };

  getDepartmentList = arr => {
    let  res = [];
    arr.map(item => {
      res.push(this.parser(item));
    });
    return res;
  };

  isChecked = (selectedKeys, eventKey) => {
    return selectedKeys.indexOf(eventKey) !== -1;
  };

  handleTransferChange = newTargetKeys => {
    this.setState({ targetKeys: newTargetKeys })
  };

  onSearch = (direction, value) => {
    if (direction === 'left') {
      this.setState({ searchValue: value });
      this.search(value)
    }
  };

  search = value => {
    if (!value) {
      this.getList();
      return -1;
    } else {
      this.setState({ loading: true });
      httpFetch.get(this.getUrl('search', value)).then(res => {
        this.setState({
          toData: res.data.map(item => this.parserTreeNode(item)),
          loading: false,
          dataSource: this.getDataSource(res.data.map(item => this.parser(item)))
        });
      }).catch(e => {
        this.setState({ loading: false });
        message.error(e.response.data.message);
      })
    }
  };

  handleOk = () => {
    const { targetKeys, dataSource } = this.state;
    const { parser } = this.props;
    const getValue = item => {
      return Object.keys(parser({})).reduce((current, key) => {
        current[key] = item[key];
        return current
      }, {});
    };
    return dataSource.filter(item => targetKeys.includes(item.id)).map(item => getValue(item))
  };

  render () {
    const { targetKeys, loading, toData, dataSource, isRelated, searchValue } = this.state;
    const { getExtraSearch, hideSubDepartment, single } = this.props;
    return (
      <Transfer
        rowKey={item => item.id}
        showSearch
        render='title'
        dataSource={dataSource}
        listStyle={() => ({ width: '340px', flex: 'none' })}
        targetKeys={targetKeys}
        onChange={this.handleTransferChange}
        className={'department'}
        searchPlaceholder={messages('common-1.key290')/*部门名称/编码*/}
        searchValue={direction => direction === 'left' ? searchValue : undefined}
        onSearch={this.onSearch}
        showSelectAll={direction => direction === 'right'}
        extraSearch={getExtraSearch}
        single={single}
        titles={[
          <div>
            {messages('common-1.key291')/*待选列表*/}
            {
              (!hideSubDepartment && !single) &&
              <Checkbox
                checked={isRelated}
                className={'special-check'}
                onChange={e => this.setState({isRelated: e.target.checked})}
              >
                {messages('common-1.key292')/*包含子部门*/}
              </Checkbox>
            }
          </div>,
          messages('common-1.key293')/*已选列表*/
        ]}
      >
        {({ direction, onItemSelect, checkedKeys }) => {
          if (direction === 'left') {
            const keys = [...checkedKeys, ...targetKeys];
            return (
              <div className={'department-ul'}>
                <Spin spinning={loading}>
                  {
                    (
                      toData.length ? (
                        <Tree
                          checkable
                          checkStrictly
                          checkedKeys={keys}
                          loadData={this.onLoadData}
                          onCheck={(values, e) => this.onCheck(values, e, onItemSelect)}
                          onSelect={(
                            _,
                            {
                              node: {
                                props: { eventKey },
                              },
                            },
                          ) => {
                            onItemSelect(eventKey, !this.isChecked(keys, eventKey));
                          }}
                        >
                          {this.renderTreeNodes(toData)}
                        </Tree>
                      ) : (
                        <div style={{lineHeight: '32px', color: '#B5C0CE'}}>{messages('common-1.key294')/*无搜索结果*/}</div>
                      )
                    )
                  }
                </Spin>
              </div>
            )
          }
        }}
      </Transfer>
    )
  }

  static propTypes = {
    isNeedCompany: PropTypes.bool,
    needEntity: PropTypes.bool,
    onRef: PropTypes.func,
    value: PropTypes.array,
    parser: PropTypes.func,
    single: PropTypes.bool,
    hideSubDepartment: PropTypes.bool
  };

}

function mapStateToProps (state) {
  return {
    company: state.login.company
  }
}

export default DepartmentTransfer
